#  调用蓝图对象
# 3.1 导入蓝图对象
import random
import re
from flask import request, make_response, current_app, jsonify
from flask import session

from info import redis_store, constants, db
from info.libs.yuntongxun.sms import CCP
from info.models import User
from info.utils.response_code import RET
from . import passport_blue
from info.utils.captcha.captcha import captcha





"""最后实现 - 退出
    也就是从浏览器删除session
    使用pop指令删除

"""
@passport_blue.route('/logout',methods=['POST'])
def logout():
    session.pop('user_id',None)
    session.pop('nick_name',None)
    session.pop('mobile',None)

    return jsonify(errno=RET.OK, errmsg='OK')



# 获取图像验证码的路由/接口
# URL: /passport/image_code?image_code_id=XXXXXXXXXX
# 参数: image_code_id


@passport_blue.route('/image_code')
def get_image_code():

    # 1. 获取参数ID
    image_code_id = request.args.get('image_code_id')

    # 2. 生成验证码内容
    name, text, image_data = captcha.generate_captcha()

    # 3. 保存到redis中 try:
    try:
        # 1. redis_store为了有智能提示, 可以增加类型注释
        # 2. set本身也是可以设置过期时间的, 在参数的第三个位置
        redis_store.set('Image_code_id_' + image_code_id, text, constants.IMAGE_CODE_REDIS_EXPIRES)
    except Exception as e:
        # 记录到日志中
        current_app.logger.error(e)
        # 返回一个错误信息 前后端的数据, 采用JSON格式来返回. 可以通知前端局部数据的处理
        # {'errno': '4001', errmsg:'保存图片验证码失败'}
        return make_response(jsonify(errno=RET.DBERR, errmsg='保存图片验证码失败'))

    # 4. 返回图像
    response = make_response(image_data)
    response.headers['Content-Type'] = 'image/jpg'
    return response
@passport_blue.route('/sms_code',methods=['POST'])
def get_sms_code():
#     获取参数
#     获取json里的内容
    params_dict = request.json
    mobile = params_dict.get('mobile')
    image_code = params_dict.get('image_code')
    image_code_id = params_dict.get('image_code_id')


#     校验参数
# 1.如果参数不全就回返回参数不全
    if not all([mobile,image_code,image_code_id]):
        return jsonify(errno=RET.PARAMERR,errmsg = '参数不全')
# 这里的errno应该是必定的参数吧
    if not re.match(r'1[3456789][0-9]{9}',mobile):
        return jsonify(errno=RET.PARAMERR,errmsg='手机号格式有误')




#     逻辑处理

    try:
        real_image_code = redis_store.get('Image_code_id_'+image_code_id)

    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, ermsg='查询数据失败')
    if not real_image_code:
        return jsonify(errno=RET.NODATA, ermsg='验证码已过期')
    # 无论对比成功与否都要删除图片验证码
    try:
        redis_store.delete('Image_code_id_'+image_code_id)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg='数据删除错误')

    # 验证码没有大小写所以要全部转换为大写或者都转换为小写
    if real_image_code.lower() != image_code.lower():
        return jsonify(errno=RET.DATAERR, ermsg='验证码不一致')
    # 这里还需要对比一下
    # 生成验证码

    # 这里还需要对比下是否已经储存在数据库里了.
    try:
        user = User.query.filter_by(mobile=mobile).first()
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg='数据库查询失败')
    if user:
        return jsonify(errno=RET.DATAEXIST, errmsg='该用户已经注册过了')

    sms_code_set = "%06d" % random.randint(0, 999999)
    # 只是为了打印一下...
    # 这里感觉需要保存到数据库
    current_app.logger.debug('sms_code:%s' % sms_code_set)
    # result = CCP().send_template_sms(mobile,[sms_code_set,5],1)
    # result=0
    # 强行改了..
    # if result !=0:
    #     return jsonify(errno=RET.THIRDERR,errmsg='短信发送失败')


    # 这里就是发送成功了
    try:
        redis_store.set('SMS_'+mobile,sms_code_set,constants.SMS_CODE_REDIS_EXPIRES)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DATAERR, errmsg='数据库错误')

    return jsonify(errno=RET.OK,errmsg='短信验证码发送成功')

    """
    注册功能的实现:
    1.获取参数--->需要获取手机号来作为id,获取输入的短信验证码,获取密码
    2.检验参数--->校验手机号码是否正确,手机号码是否注册过,校验输入的短信验证码是否正确
    3.储存参数(注册成功了),将这些信息储存到redis中
    4.登陆,其实就是设置session,将手机号(id)
    url = "/passport/register"
    mobile = 手机号
    smscode = 手机验证码
    password = 密码
    请求类型 = post
    """
@passport_blue.route('/register',methods=['post'])
def register():
    # 获取浏览器的参数
    json_dict = request.json
    mobile =json_dict.get('mobile')
    smscode = json_dict.get('smscode')
    password = json_dict.get('password')
    # 这里是储存到数据库的值redis_store.set('SMS_' + mobile, sms_code_set, constants.SMS_CODE_REDIS_EXPIRES)
#     检验参数
    if not all ([mobile,smscode,password]):

        return jsonify(errno=RET.PARAMERR, errmsg='参数不全')

    if not re.match(r'1[3-9]\d{9}',mobile):
        return jsonify(errno=RET.DATAERR,errmsg='手机号码不正确')

    try:
        real_code = redis_store.get('SMS_' + mobile)

    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg='数据读取错误')

    if real_code != smscode or not real_code:
        return jsonify(errno=RET.PARAMERR, errmsg='验证码不一致或已经过期')



#     接下来就是排除了一切错误的正确结果,将其添加到数据库

    try:
        user = User.query.filter_by(mobile=mobile).first()

    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.PARAMERR,errmsg='数据查询失败')

    if user:
        return jsonify(errno=RET.DATAEXIST,errmsg='该用户已经存在')
        #
    # 创建数据库操作模型
    user_model = User()
    user_model.mobile = mobile
    # 这里密码没有加密
    user_model.password = password
    user_model.nick_name = mobile
    # user_model.password_hash = password

    try:
        db.session.add(user_model)
        db.session.commit()
    except Exception as e:
        current_app.logger.error(e)
        db.session.rollback()
        return jsonify(errno=RET.DATAERR,errmsg='数据库添加失败')

    # 实现登陆,也就是添加到session
    session['user_id']=user_model.id
    session['nick_name']=user_model.nick_name
    print(user_model.nick_name)
    print(user_model.id)
    session['mobile']=user_model.mobile
    return jsonify(errno=RET.OK,errmsg='注册失败')





"""

登陆代码实现:
1.需要前段获取到客户输入的账号以及密码,将其使用ajax发送到后端
var mobile
var password
var params = {
        "mobile": mobile,
        "password": password,
    }

2.后端:
    1.需要获取前端传过来的信息
    2.校验数据
        1.从数据库中读取数据(获取密码),使用的key为mobile
        2.能够读取到说明用户存在,读取不到说明用户没有注册
        3.将读取到的数据和获取的数据进行比对,成功说明登陆成功,没有成功说明
        密码错误
        4.当登陆成功时需要设置session信息,设置的信息可以有昵称,mobile,头像.



"""
@passport_blue.route('/login',methods=["post"])
def login():
    """
    1.获取浏览器发送来的数据
    2.检验数据
    3.处理逻辑
    4.返回数据


    """
    # 1.获取数据password和mobile
    json_dict = request.json
    password = json_dict.get('password')
    mobile = json_dict.get('mobile')

# 检验参数,检验密码是否正确,检验账号是否存在
#     想要检验得先从数据库取出密码
    if not all([password,mobile]):
        return jsonify(errno=RET.PARAMERR, errmsg='参数不全')

    if not re.match(r"1[3-9]\d{9}",mobile):
        return jsonify(errno=RET.DATAERR, errmsg='账号不符合规定')

    try:
        # 这里的user是表示一个对象,一个表中的符合条件的一行
        user = User.query.filter_by(mobile=mobile).first()

    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR,errmsg='数据库读取失败')
#     这里需要判断user是否为none
    if not user:
        return jsonify(errno=RET.USERERR,errmsg='用户名或密码错误')
    # 使用user对象获取对应的密码进行对比
    if not user.check_passowrd(password):
        return jsonify(errno=RET.PWDERR, errmsg='用户名或密码错误')

    session['user_id'] = user.id
    session['nick_name'] = user.nick_name
    session['mobile'] = user.mobile
    print(user.mobile)

    return jsonify(errno=RET.OK,errmsg='注册成功')

